package com.example.interview.example.mobileBilling;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

//移动公司的抽象客户类，这里不需要区分普通用户和VIP用户，  而是把他们抽象成用户这个父类，这样就可以采用统一的方式来调用他们各自的行为，
// 普通用户和VIP用户的行为差异，在它们各自的方法内部体现(VIPCustomer,CommonCustomer)，这正是充分利用了面向对象的抽象和多态特性。
/**
 * 1.定义了用户名称和入网时间；还定义了4个List集合的成员变量，分别用于存储用户每次拨打的电话时间、每次发送的短信数量和
 *      每次传输的数据量，以及用户的操作列表；此外， Customer类中还定义了一个用于计算当月账单费用的策略存储对象，它用于
 *      存储用户选择的各项功能套餐的策略对象。
 * 2.定义打电话、发短信、传输数据的方法，这些方法分别为对应的List集合增加记录，并且都需要向操作列表集合中增加记录。此外，
 *      由于普通用户和VIP用户定套餐和退订套餐的方式有很大的区别，所以，这两个功能在Customer类中对应的方法被定义成了抽象的，这两
 *      个方法由普通用户和VIP用户根据自己的实际情况去具体实现。
 * 3.定义了一个countMonthMoney方法来计算用户当前月的账单费用，首先从电话、短信、数据等集合中累加出各项功能的数量，对于新用户，
 *      则减去新用户要优惠的数量，然后再将这些数量分别传递给用户订购的相应的策略对象去计算费用，最后汇总和打印出总费用。
 */
public abstract class Customer {
    protected String name;
    //用户入网的时间
    private Date joinTime;
    private int customerType = 0;
    protected List<ActionRecord> actionRecords = new ArrayList<ActionRecord>();

    //积累的结果只表示当月的所有通话记录，不代表所有历史记录
    private ArrayList phoneRecords = new ArrayList();
    //积累的结果只表示当月的所有短信记录，不代表所有历史记录
    private ArrayList messageRecords = new ArrayList();
    //积累的结果只表示当月的所有数据传送记录，不代表所有历史记录
    private ArrayList dataRecords = new ArrayList();
    protected PackStrategy packStrategy;

    public void monthBegin(){ // 清除用户的记录信息
        phoneRecords.clear();
        messageRecords.clear();
        dataRecords.clear();
        actionRecords.clear();
    }

    public Customer(String name,Date joinTime,int customerType){
        this.name = name;
        this.joinTime = joinTime;
        this.customerType = customerType;
    }

    public String toString(){
        return name;
    }

    public void callPhone(int times){
        phoneRecords.add(times);
        actionRecords.add(new ActionRecord("打电话",times + "分钟"));
    }
    public void sendMessage(int numbers){
        messageRecords.add(numbers);
        actionRecords.add(new ActionRecord("发短信",numbers + "条"));
    }
    public  void transferData(int size){
        dataRecords.add(size);
        actionRecords.add(new ActionRecord("传数据",size + "k"));
    }

    /**
     * @param currentMonth 正在被计费处理的当月的日期，
     * 注意：日字段设置为1，以便于方法内部计算是否是新用户
     *   计算用户当前月的账单费用，首先从电话、短信、数据等集合中累加出各项功能的数量，对于新用户，
     *   则减去新用户要优惠的数量，然后再将这些数量分别传递给用户订购的相应的策略对象去计算费用，最后汇总和打印出总费用。
     */
    public int countMonthMoney(Date currentMonth){
        System.out.println("------------->joinTime(入网日期)------------->" + DateUtil.formatDateToMonth(joinTime));
        System.out.println("------------->currentMonth(当月计费日期)------------->" + DateUtil.formatDateToMonth(currentMonth));
        System.out.println("------------->joinTime.after(currentMonth)------->" + joinTime.after(currentMonth));
        boolean newcome = joinTime.after(currentMonth);// 前者在后者后面(前者是比较新的日期) 注意：相等的时候也是true !!!

        int totalPhone = gatherRecords(phoneRecords);//获取(随机生成的打电话、发短信、流量的使用量化数据)
        int totalMessage = gatherRecords(messageRecords);
        int totalData = gatherRecords(dataRecords);

        int freePhone = 0;
        int freeMessage = 0;
        int freeData = 0;
        // customerType == 0 ? "common" : "vip"
        // businessType:  String[] businesses = {"phone", "message", "data"};
        if(newcome){//if 入网日期==当前日期, 则从配置文件conf.properties(通讯赠送)自定义测试数据
            freePhone = ConfigManager.getNewCustomerFree(customerType,0);
            freeMessage = ConfigManager.getNewCustomerFree(customerType,1);
            freeData = ConfigManager.getNewCustomerFree(customerType,2);
        }

        //统计计算需收费的业务
        int chargePhone =   totalPhone   > freePhone   ? totalPhone    - freePhone   : 0;
        int chargeMessage = totalMessage > freeMessage ? totalMessage  - freeMessage : 0;
        int chargeData =    totalData    > freeData    ? totalData     - freeData    : 0;

        //汇总打印:包括姓名，入网日期，统计月份，通话清单，费用清单，总费用。
        System.out.println(name + "," + DateUtil.formatDateToDay(joinTime) + "入网.");
        System.out.println(" 操作清单如下-----");
        for(int i=0;i<actionRecords.size();i++){ //打印(随机生成的打电话、发短信、流量的使用量化数据)
            System.out.println("  " + actionRecords.get(i));
        }
        System.out.println(" 统计清单如下-----");
        System.out.println("  通话:" + phoneRecords + "分钟:短信" + messageRecords + "条:数据" + dataRecords + "k");
        System.out.println("  通话累计:" + totalPhone + "分钟，减除新开户" + freePhone + "分钟，实际收费" + chargePhone + "分钟");
        System.out.println("  短信累计:" + totalMessage + "条，减除新开户" + freeMessage + "条，实际收费" + chargeMessage + "条");
        System.out.println("  数据累计:" + totalData + "k，减除新开户" + freeData + "k，实际收费" + chargeData + "k");

        ComputeStrategy phoneStrategy = packStrategy.getValidPhonePack(currentMonth);
        ComputeStrategy messageStrategy = packStrategy.getValidMessagePack(currentMonth);
        ComputeStrategy dataStrategy = packStrategy.getValidDataPack(currentMonth);

        int sum = 0;
        //VIP用户才有月租金或基本费
        Rent rent = packStrategy.getValidRent(currentMonth);
        if(rent != null){
            int rentMoney = rent.coputeRent(joinTime,currentMonth);
            sum +=  rentMoney;
            System.out.println("  月租费或基本费：" + rentMoney + "厘钱");
        }

        sum += phoneStrategy.computeMoney(chargePhone);
        sum += messageStrategy.computeMoney(chargeMessage);
        sum += dataStrategy.computeMoney(chargeData/10);
        System.out.println("  总计：" + sum/1000f + "元钱");
        return sum;
    }

    private int gatherRecords(ArrayList records){
        int sum = 0;
        for(int i=0;i<records.size();i++){
            sum +=  (Integer)(records.get(i));
        }
        return sum;
    }

    public abstract void randomCancelPack(Date month);
    public abstract void randomOrderPack(Date month);

}
